﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging.Filters;
using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;
using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;

namespace mki.Backup.Helper
{
	/// <summary>
	/// Custom logger class
	/// </summary>
	internal static class CustomLogger
	{
		#region Fields (1)

		private static LogWriter writer;

		#endregion Fields

		#region Properties (1)

		/// <summary>
		/// Gets the config block.
		/// </summary>
		/// <returns></returns>
		private static LoggingSettings loggingSettings
		{
			get
			{
				var logSettings = null as LoggingSettings;

				try
				{
					if (ConfigurationManager.GetSection("loggingConfiguration") != null && ConfigurationManager.GetSection("loggingConfiguration").GetType() == typeof(LoggingSettings))
					{
						logSettings = (LoggingSettings)ConfigurationManager.GetSection("loggingConfiguration");
					}
				}
				catch (Exception ex)
				{
					if (Debugger.IsAttached)
					{
						Console.WriteLine(String.Format("{0}\n{1}", ex.Message, ex.StackTrace));
					}
				}
				return logSettings;
			}
		}

		#endregion Properties

		#region Methods (3)

		// Public Methods (2) 

		/// <summary>
		/// Removes the logger.
		/// </summary>
		public static void Dispose()
		{
			try
			{
				// try to clean up
				if (writer != null)
				{
					writer.Dispose();
					writer = null;
				}
			}
			catch
			{
				// todo: write to eventlog
			}
		}

		/// <summary>
		/// Writes the specified message.
		/// </summary>
		/// <param name="logFileNameAndPath">The log file name and path.</param>
		/// <param name="message">The message.</param>
		/// <param name="category">The category.</param>
		public static void Write(String logFileNameAndPath, String message, String category)
		{
			if (writer == null) { createLogger(logFileNameAndPath); }

			var entry = new LogEntry();
			entry.Categories.Add(category);
			entry.Message = message;
			writer.Write(entry);
		}
		// Private Methods (1) 

		/// <summary>
		/// Writes log data to custom file.
		/// </summary>
		/// <param name="logFileAndPath">The log file and path.</param>
		private static void createLogger(String logFileAndPath)
		{
			if (loggingSettings != null && writer == null && !String.IsNullOrWhiteSpace(logFileAndPath))
			{
				// create textformatter depending on stuff in config, we only want to change loacation
				var textFormatterData = ((TextFormatterData)loggingSettings.Formatters.Get(0));
				if (textFormatterData != null && !String.IsNullOrWhiteSpace(textFormatterData.Template))
				{
					var textFormatter = new TextFormatter(textFormatterData.Template);

					var logFileListernerData = ((RollingFlatFileTraceListenerData)(loggingSettings.TraceListeners).Get(0));
					if (logFileListernerData != null)
					{
						// create the rolling flat file listener
						var logFileListener = new RollingFlatFileTraceListener(logFileAndPath, logFileListernerData.Header, logFileListernerData.Footer, textFormatter, logFileListernerData.RollSizeKB, logFileListernerData.TimeStampPattern, logFileListernerData.RollFileExistsBehavior, logFileListernerData.RollInterval);

						// get logsources
						var allEvents = new LogSource(loggingSettings.SpecialTraceSources.AllEventsTraceSource.Name, new List<TraceListener> { logFileListener }, loggingSettings.SpecialTraceSources.AllEventsTraceSource.DefaultLevel, true);

						// get tracesources
						IDictionary<string, LogSource> traceSources = new Dictionary<string, LogSource> { { allEvents.Name, allEvents } };

						// add it to logsource
						writer = new LogWriter(
									new ILogFilter[0],
									traceSources,
									allEvents,
									allEvents,
									allEvents,
									loggingSettings.DefaultCategory,
									loggingSettings.TracingEnabled,
									loggingSettings.LogWarningWhenNoCategoriesMatch
								);
					}
				}
			}
		}

		#endregion Methods
	}
}